import 'dart:convert';
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'gg_requestSign.dart';

class DGGNetWorking {
  static const bool inProduction =
      const bool.fromEnvironment("dart.vm.product");
  static bool isOpenResign = true;
  static Dio? dio;
  static String? requestBaseURL;
  static const String GET = 'get';
  static const String POST = 'post';
  static String cookie = "";

  /// 配置dio
  static void config(String baseURL, bool openResign) {
    requestBaseURL = baseURL;
    isOpenResign = openResign;
    if (dio == null) {
      dio = createInstance();
    }
    dio?.options.baseUrl = requestBaseURL!;
  }

  ///添加公共headers
  static void addCommonHeaders(Map<String, dynamic> headers) {
    if (dio == null) {
      dio = createInstance();
    }
    dio?.options.headers.addAll(headers);
  }

  ///设置代理，用于抓包，仅Debug模式且调用了该方法时生效
  static void addSettingForProxy(String proxy) {
    if (dio == null) {
      dio = createInstance();
    }
    (dio?.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      client.findProxy = (url) {
        // 用1个开关设置是否开启代理
        String resultProxy = 'DIRECT';
        if (proxy != null && proxy.isNotEmpty) {
          resultProxy = 'PROXY ' + proxy;
        }
        return resultProxy;
      };
      //支持https抓包设置
      if (proxy != null && proxy.isNotEmpty) {
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
      }
    };
  }

  static Dio createInstance() {
    if (dio == null) {
      ///初始化配置
      BaseOptions _options = BaseOptions(
        receiveTimeout: 100000,
        sendTimeout: 15000,
        baseUrl: requestBaseURL ?? '',
        headers: {
          HttpHeaders.userAgentHeader: "dio",
          // "api": "v1",
        },
        // Transform the response data to a String encoded with UTF8.
        // The default value is [ResponseType.JSON].
        responseType: ResponseType.json,
      );
      dio = new Dio(_options);
      //设置请求是建立Socket连接的超时时间
      dio?.options.connectTimeout = 10000000;
      // dio.options.headers = {HttpHeaders.acceptHeader:"application/json"};
      dio!.interceptors..add(LogInterceptor());
      // ..add(InterceptorsWrapper(onRequest: (RequestOptions options, RequestInterceptorHandler hander) {
      //   print('请求即将发送');
      //   super.onRequest(options, hander);
      //   // 在请求被发送之前做一些事情
      //   // return options; //continue
      //   // 如果你想完成请求并返回一些自定义数据，可以返回一个`Response`对象或返回`dio.resolve(data)`。
      //   // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义数据data.
      //   // 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象，或返回`dio.reject(errMsg)`，
      //   // 这样请求将被中止并触发异常，上层catchError会被调用。
      // }, onResponse: (Response response, ResponseInterceptorHandler hander) {
      //   // 在返回响应数据之前做一些预处理
      //   // return response; // continue
      // }, onError: (DioError e, ErrorInterceptorHandler errorHander) {
      //   // 当请求失败时做一些预处理
      //   // return e; //continue
      //   errorHander.next(e);
      // }));
    }
    return dio!;
  }

  /// 清空 dio 对象
  static clear() {
    dio?.clear();
  }

  static _setCookie(String cookies) {
    if (cookies.isNotEmpty && !cookies.contains("null")) {
      cookie = cookies.substring(1, cookies.length - 1);
      print("请求返回的cookie" + cookie);
    }
  }

  static Future<Map<String, dynamic>> getRequest(String url,
      {params, header}) async {
    params = params ?? {};
    header = header ?? {};
    Dio dio = createInstance();
    try {
      if (isOpenResign == true) {
        //开启验签的情况
        Response response;
        String requestParams = DGGRequestSign.sortFormatParams(params);
        String requestURL = '';
        if (url.isNotEmpty && url.indexOf('?') != -1) {
          //已有带?参数
          requestURL = '$url&$requestParams';
        } else {
          requestURL = '$url?$requestParams';
        }
        //获取签名

        Map<String, dynamic> addHeader =
            DGGRequestSign.generateGetHeader(params, header);
        if (cookie.isNotEmpty == true) {
          addHeader.addAll({"cookie": cookie});
        }
        dio.options.headers.addAll(addHeader);
        String getURL = requestURL;
        try {
          getURL = Uri.encodeFull(requestURL);
        } catch (e) {}
        if (inProduction == false) {
          /// 打印请求相关信息：请求地址、请求方式、请求参数
          print('请求地址：【GET' + getURL + '】');
          print('请求参数：' + params.toString());
        }
        response = await dio.get(getURL, queryParameters: {});

        _setCookie(response.headers["set-cookie"].toString());

        String res = response.data;
        if (inProduction == false) {
          /// 打印响应相关信息
          print('响应数据(处理前)：' + res);
        }

        ///再次验证是否符合标准Json，非标准，抛出异常
        try {
          var map = json.decode(res);
          return map;
        } catch (e) {
          if (inProduction == false) {
            /// 打印请求失败相关信息
            print('请求出错：' + e.toString());
          }
          Map<String, Object> errorInfo = {
            'code': '-1',
            'message': '请求错误',
            'data': {}
          };
          return errorInfo;
        }
      } else {
        //不开启验签的情况
        dio.options.headers.addAll(header);
        Response response = await dio.get(url, queryParameters: {});

        _setCookie(response.headers["set-cookie"].toString());
        if (response.data is Map) {
          return response.data;
        }

        String res = response.data;
        if (inProduction == false) {
          /// 打印响应相关信息
          print('响应数据(处理前)：' + res);
        }

        ///再次验证是否符合标准Json，非标准，抛出异常
        try {
          var map = json.decode(res);
          return map;
        } catch (e) {
          if (inProduction == false) {
            /// 打印请求失败相关信息
            print('请求出错：' + e.toString());
          }
          Map<String, Object> errorInfo = {
            'code': '-1',
            'message': '请求错误',
            'data': {}
          };
          return errorInfo;
        }
      }
    } on DioError catch (e) {
      if (inProduction == false) {
        /// 打印请求失败相关信息
        print('请求出错：' + e.toString());
      }
      Map<String, Object> resultModel = {};
      if (e.response != null) {
        resultModel.addAll({'code': '${e.response!.statusCode}'});
      }
      resultModel.addAll({'msg': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'message': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'data': {}});
      return resultModel;
    }
  }

  static Future<Map<String, dynamic>> postRequest(String url,
      {params, header}) async {
    params = params ?? {};
    header = header ?? {};
    Dio dio = createInstance();
    try {
      if (isOpenResign == true) {
        //开启验签的情况
        Response response;
        if (inProduction == false) {
          /// 打印请求相关信息：请求地址、请求方式、请求参数
          print('请求地址：【POST   ' + url + '】');
          print('请求参数：' + params.toString());
        }
        //获取签名
        Map<String, dynamic> addHeader =
            DGGRequestSign.generatePostHeader(params, header);
        dio.options.headers.addAll(addHeader);
        response = await dio.post(url, data: params);
        String res = response.data;
        _setCookie(response.headers["set-cookie"].toString());
        if (inProduction == false) {
          print('响应数据(处理前)：' + res);
        }

        ///再次验证是否符合标准Json，非标准，抛出异常
        try {
          var map = json.decode(res);
          return map;
        } catch (e) {
          if (inProduction == false) {
            /// 打印请求失败相关信息
            print('请求出错：' + e.toString());
          }
          Map<String, Object> errorInfo = {
            'code': '-1',
            'message': '请求错误',
            'data': {}
          };
          return errorInfo;
        }
      } else {
        //不开启验签的情况
        dio.options.headers.addAll(header);
        Response response = await dio.post(url, data: params);
        Map<String, dynamic> res = response.data;

        _setCookie(response.headers["set-cookie"].toString());
        if (inProduction == false) {
          /// 打印响应相关信息
          print('响应数据(处理前)：' + res.toString());
        }

        ///再次验证是否符合标准Json，非标准，抛出异常
        try {
          var map = res; //json.decode(res);
          return map;
        } catch (e) {
          if (inProduction == false) {
            /// 打印请求失败相关信息
            print('请求出错：' + e.toString());
          }
          Map<String, Object> errorInfo = {
            'code': '-1',
            'message': '请求错误',
            'data': {}
          };
          return errorInfo;
        }
      }
    } on DioError catch (e) {
      if (inProduction == false) {
        /// 打印请求失败相关信息
        print('请求出错：' + e.toString());
      }
      Map<String, Object> resultModel = {};
      if (e.response != null) {
        resultModel.addAll({'code': '${e.response!.statusCode}'});
      }
      resultModel.addAll({'msg': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'message': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'data': {}});
      return resultModel;
    }
  }

  /// 表单提交公共方法，不验签
  static Future<Map<String, dynamic>> postRequestFormData(
      String url, FormData formData, Function(int, int) onSend) async {
    Dio dio = createInstance();
    try {
      Response response;
      response = await dio.post(url, data: formData, onSendProgress: onSend);
      String res = response.data;

      /// 打印响应相关信息
      if (inProduction == false) {
        /// 打印请求失败相关信息
        print('响应数据(处理前)：' + res);
      }

      ///再次验证是否符合标准Json，非标准，抛出异常
      try {
        var map = json.decode(res);
        return map;
      } catch (e) {
        if (inProduction == false) {
          /// 打印请求失败相关信息
          print('请求出错：' + e.toString());
        }
        Map<String, Object> errorInfo = {
          'code': '-1',
          'message': '请求错误',
          'data': {}
        };
        return errorInfo;
      }
    } on DioError catch (e) {
      if (inProduction == false) {
        /// 打印请求失败相关信息
        print('请求出错：' + e.toString());
      }
      Map<String, Object> resultModel = {};
      if (e.response != null) {
        resultModel.addAll({'code': '${e.response!.statusCode}'});
      }
      resultModel.addAll({'msg': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'message': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'data': {}});
      return resultModel;
    }
  }

  /// 表单提交公共方法，不验签
  static Future<Map<String, dynamic>> postRequestFormDataToString(
      String url, FormData formData, Function(int, int) onSend) async {
    Dio dio = createInstance();
    try {
      Response response;
      response = await dio.post(url, data: formData, onSendProgress: onSend);
      String res = response.toString();

      /// 打印响应相关信息
      if (inProduction == false) {
        /// 打印请求失败相关信息
        print('响应数据(处理前)：' + res);
      }

      ///再次验证是否符合标准Json，非标准，抛出异常
      try {
        var map = json.decode(res);
        return map;
        // return res;
      } catch (e) {
        if (inProduction == false) {
          /// 打印请求失败相关信息
          print('请求出错：' + e.toString());
        }
        Map<String, Object> errorInfo = {
          'code': '-1',
          'message': '请求错误',
          'data': {}
        };
        return errorInfo;
      }
    } on DioError catch (e) {
      if (inProduction == false) {
        /// 打印请求失败相关信息
        print('请求出错：' + e.toString());
      }
      Map<String, Object> resultModel = {};
      if (e.response != null) {
        resultModel.addAll({'code': '${e.response!.statusCode}'});
      }
      resultModel.addAll({'msg': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'message': '网络有点问题，请稍后再试～'});
      resultModel.addAll({'data': {}});
      return resultModel;
    }
  }
}
